home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / mus / play / tracker_4_31.lzh / tracker / Arch / Sparc / audio.c next >
C/C++ Source or Header  |  1995-05-12  |  9KB  |  434 lines

  1. /* sparc/audio.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* $Id: audio.c,v 4.15 1995/05/12 20:40:46 espie Exp espie $
  6.  * $Log: audio.c,v $
  7.  * Revision 4.15  1995/05/12  20:40:46  espie
  8.  * Added frequency change.
  9.  *
  10.  * Revision 4.14  1995/05/12  13:52:39  espie
  11.  * New synchronization.
  12.  *
  13.  * Revision 4.13  1995/03/03  14:22:55  espie
  14.  * Fixed audio info bug.
  15.  *
  16.  * Revision 4.12  1995/02/26  23:07:14  espie
  17.  * solaris.
  18.  *
  19.  * Revision 4.11  1995/02/25  15:44:15  espie
  20.  * discard_buffer incorrect.
  21.  *
  22.  * Revision 4.10  1995/02/24  15:36:39  espie
  23.  * Finally fixed speed/sync/late start.
  24.  *
  25.  * Revision 4.9  1995/02/24  13:48:39  espie
  26.  * Fixed minor bug (interaction between pause and -sync).
  27.  *
  28.  * Revision 4.8  1995/02/24  13:43:52  espie
  29.  * Added -sync feature.
  30.  * In the absence of -sync, pause half a second at start to allow for
  31.  * data to accumulate in buffer first.
  32.  * Suppressed update freq on the fly since audioctl does not allow it.
  33.  *
  34.  * Revision 4.7  1995/02/23  22:41:45  espie
  35.  * Added # of bits.
  36.  *
  37.  * Revision 4.6  1995/02/23  16:42:27  espie
  38.  * Began conversion to `common' model.
  39.  *
  40.  * Revision 4.5  1995/02/23  13:52:30  espie
  41.  * primary, secondary -> primary+secondary, primary-secondary
  42.  * strike out 2 multiplications out of 4 !
  43.  *
  44.  * Revision 4.4  1995/02/21  17:57:55  espie
  45.  * Internal problem: RCS not working.
  46.  *
  47.  * Revision 4.3  1995/02/01  16:43:47  espie
  48.  * 23 bit samples.
  49.  *
  50.  * Revision 4.2  1994/01/13  09:19:08  espie
  51.  * Forgotten something.
  52.  *
  53.  * Revision 4.0  1994/01/11  18:16:36  espie
  54.  * New release.
  55.  *
  56.  * Revision 3.14  1993/12/04  16:12:50  espie
  57.  * BOOL -> boolean.
  58.  * Merged ss10/solaris.
  59.  * Merged support for solaris together.
  60.  * Fixed /16 bug.
  61.  * Corrected mix problem.
  62.  * restore stty.
  63.  * Sync pseudo call.
  64.  * Added update_frequency call, mostly unchecked
  65.  * Added finetune.
  66.  * Protracker commands.
  67.  *
  68.  * Revision 1.3  1992/11/17  15:38:00  espie
  69.  * discard_buffer() call for snappier interface calls.
  70.  * - Unified support for all sparcs.
  71.  * - moved down to level 2 io.
  72.  */
  73.  
  74. #include "defs.h"
  75. #include "extern.h"
  76. #ifdef SOLARIS
  77. #include <sys/audioio.h>
  78. #else
  79. #include <sun/audioio.h>
  80. #endif
  81. #include <sys/ioctl.h>
  82. #include <fcntl.h>
  83. #include <stropts.h>
  84. #include <signal.h>
  85.      
  86. #define DEFAULT_SET_MIX
  87. #define DEFAULT_BUFFERS
  88. #define NEW_OUTPUT_SAMPLES_AWARE
  89. #define NEW_FUNCS
  90.  
  91. #include "Arch/common.c"
  92.  
  93. /* things that aren't defined in all sun/audioio.h */
  94.  
  95. #ifndef AUDIO_ENCODING_LINEAR
  96. #define AUDIO_ENCODING_LINEAR (3)
  97. #endif
  98. #ifndef AUDIO_GETDEV
  99. #define AUDIO_GETDEV    _IOR(A, 4, int)
  100. #endif
  101. #ifndef AUDIO_DEV_UNKNOWN
  102. #define AUDIO_DEV_UNKNOWN (0)
  103. #endif
  104. #ifndef AUDIO_DEV_AMD
  105. #define AUDIO_DEV_AMD (1)
  106. #endif
  107.  
  108. ID("$Id: audio.c,v 4.15 1995/05/12 20:40:46 espie Exp espie $")
  109.  
  110. LOCAL int audio;
  111. LOCAL int written;
  112. LOCAL int wait_samples;
  113. LOCAL int tsync;
  114.  
  115. LOCAL int ADVANCE_TAGS=    -1;
  116.  
  117. LOCAL struct audio_info ainfo, ainfo2;
  118.  
  119. /* set_synchronize(): pause the audio device at start of play,
  120.  * in order to accumulate enough samples before playing
  121.  */
  122. LOCAL void set_synchronize()
  123.     {
  124.     written = ainfo.play.eof;
  125.     if (!ainfo2.play.pause)
  126.         {
  127.         ainfo2.play.pause = TRUE;
  128.         ioctl(audio, AUDIO_SETINFO, &ainfo2);
  129.             /* number of samples to accumulate */
  130.         wait_samples = ainfo.play.sample_rate / 2;
  131.         }
  132.     else
  133.         wait_samples = 0;
  134.     }
  135.  
  136. LOCAL int possible[] = { 8000, 9600, 11025, 16000, 18900, 22050, 32000,
  137.     37800, 44100, 48000, 0};
  138.  
  139. int open_audio(f, s)
  140. int f;
  141. int s;
  142.    {
  143.     int type;
  144.  
  145.     int basic;
  146. #ifdef SOLARIS
  147.     audio_device_t dev;
  148.  
  149.     audio = open("/dev/audio", O_WRONLY);
  150. #else
  151.    audio = open("/dev/audio", O_WRONLY|O_NDELAY);
  152. #endif
  153.  
  154.  
  155.     basic = 0;
  156.    if (audio == -1)
  157.         end_all("Error: could not open audio");
  158.  
  159.         /* round frequency to acceptable value */
  160.     f = best_frequency(f, possible, 22050);
  161.  
  162.         /* check whether we know about AUDIO_ENCODING_LINEAR */
  163.     AUDIO_INITINFO(&ainfo);
  164.     AUDIO_INITINFO(&ainfo2);
  165. #ifdef SOLARIS
  166.     ioctl(audio, AUDIO_GETDEV, &dev);
  167.     if (strcmp(dev.name, "SUNW,dbri") != 0)
  168. #else
  169.     if (ioctl(audio, AUDIO_GETDEV, &type) ||
  170.     type == AUDIO_DEV_UNKNOWN || type == AUDIO_DEV_AMD || basic)
  171. #endif
  172.         {
  173.             /* not a new ss5/10/20 -> revert to base quality audio */
  174.         stereo = 0;
  175.         dsize = 1;
  176.         f = 8000;
  177.         ainfo.play.encoding = AUDIO_ENCODING_ULAW;
  178.         ainfo.play.channels = 1;
  179.         }
  180.     else
  181.         {
  182.             /* tentative set up */
  183.         stereo = s;
  184.         ainfo.play.precision = 16;
  185.         dsize = 2;
  186.         if (stereo)
  187.             ainfo.play.channels = 2;
  188.         else
  189.             ainfo.play.channels = 1;
  190.             /* try it */
  191.         ainfo.play.encoding = AUDIO_ENCODING_LINEAR;
  192.         }
  193.     ainfo.play.sample_rate = f;
  194.     if (ioctl(audio, AUDIO_SETINFO, &ainfo) != 0)
  195.         /* didn't work: fatal problem */
  196.         end_all("Error: AUDIO_SETINFO");
  197.     idx = 0;
  198.     samples_max = ainfo.play.channels*ainfo.play.sample_rate;
  199.     buffer = (char *)malloc(dsize*samples_max);
  200.     buffer16 = (short *)buffer;
  201.     if (!buffer)
  202.         end_all("Error: could not allocate buffer");
  203.  
  204.     set_synchronize();
  205.     return f;
  206.     }
  207.  
  208. void set_synchro(s)
  209. int s;
  210.     {
  211.     tsync = s;
  212.     }
  213.  
  214. LOCAL int newfreq;
  215.  
  216. int update_frequency()
  217.     {
  218.     if (newfreq)
  219.         {
  220.         newfreq = 0;
  221.         samples_max = ainfo.play.channels * ainfo.play.sample_rate;
  222.         buffer = realloc(buffer, dsize * samples_max);
  223.         buffer16 = (short *)buffer;
  224.         return ainfo.play.sample_rate;
  225.         }
  226.     else
  227.         return 0;
  228.  
  229.     /* the current implementation of the audio device does not allow
  230.      * output frequency change through /dev/audioctl
  231.      *    -> this code is not needed 
  232.     int oldfreq;
  233.  
  234.     oldfreq = ainfo.play.sample_rate;
  235.     if (ioctl(audio, AUDIO_GETINFO, &ainfo) == 0)
  236.         {
  237.         if (oldfreq != ainfo.play.sample_rate)
  238.             {
  239.             samples_max = ainfo.play.channels * ainfo.play.sample_rate;
  240.             buffer = realloc(buffer, dsize * samples_max);
  241.             buffer16 = (short *)buffer;
  242.             return ainfo.play.sample_rate;
  243.             }
  244.         }
  245.     return 0;
  246.      */
  247.     }
  248.  
  249. void audio_ui(c)
  250. int c;
  251.     {
  252.     int i;
  253.  
  254.     switch(c)
  255.         {
  256.     case '+':
  257.         if (audio & ainfo.play.encoding == AUDIO_ENCODING_LINEAR)
  258.             {
  259.             for (i = 0; ; i++)
  260.                 if (possible[i] == ainfo.play.sample_rate)
  261.                     break;
  262.             if (possible[i+1])
  263.                 {
  264.                 ainfo.play.sample_rate = possible[i+1];
  265.                 if (ioctl(audio, AUDIO_SETINFO, &ainfo) == 0)
  266.                     newfreq = 1;
  267.                 }
  268.             }
  269.         break;
  270.     case '-':
  271.         if (audio & ainfo.play.encoding == AUDIO_ENCODING_LINEAR)
  272.             {
  273.             for (i = 0; ; i++)
  274.                 if (possible[i] == ainfo.play.sample_rate)
  275.                     break;
  276.             if (i)
  277.                 {
  278.                 ainfo.play.sample_rate = possible[i-1];
  279.                 if (ioctl(audio, AUDIO_SETINFO, &ainfo) == 0)
  280.                     newfreq = 1;
  281.                 }
  282.             }
  283.         break;
  284.     default:
  285.         }
  286.     }
  287.  
  288.  
  289. void output_samples(left, right, n)
  290. int left, right, n;
  291.    {
  292.  
  293.     switch(ainfo.play.encoding)
  294.         {
  295.     case AUDIO_ENCODING_LINEAR:
  296.         add_samples16(left, right, n);
  297.         break;
  298.     case AUDIO_ENCODING_ULAW:
  299.         buffer[idx++] = linear2ulaw((left + right) >> (n-14));
  300.         break;
  301.     default:
  302.         end_all("Error:Unknown audio encoding");
  303.         }
  304.     }
  305.  
  306.  
  307. /* synchronize stuff with audio output */
  308.  
  309. struct tagged
  310.     {
  311.     struct tagged *next;            /* simply linked list */
  312.     void (*f) P((GENERIC *));    /* function to call */
  313.     GENERIC p;                        /* and parameter */
  314.     int when;                        /* number of chunks to let go before calling */
  315.     } 
  316.     *start,    /* what still to output */
  317.     *end;    /* where to add new tags */
  318.  
  319.  
  320.  
  321. /* flush_tags: use tags that have gone by recently */
  322. LOCAL void flush_tags()
  323.     {
  324.     ioctl(audio, AUDIO_GETINFO, &ainfo);
  325.     if (start)
  326.         {
  327.         while (start && start->when <= ainfo.play.eof + ADVANCE_TAGS)
  328.             {
  329.             struct tagged *tofree;
  330.  
  331.             (*start->f)(start->p);
  332.             tofree = start;
  333.             start = start->next;
  334.             free(tofree);
  335.             }
  336.         }
  337.     }
  338.  
  339. /* remove unused tags at end */
  340. LOCAL void remove_pending_tags()
  341.     {
  342.     while (start)
  343.         {
  344.         struct tagged *tofree;
  345.  
  346.         tofree = start;
  347.         start = start->next;
  348.         free(tofree);
  349.         }
  350.     }
  351.  
  352. void sync_audio(function, parameter)
  353. void (*function) P((void *));
  354. GENERIC parameter;
  355.     {
  356.     struct tagged *t;
  357.  
  358.     t = malloc(sizeof(struct tagged));
  359.     if (!t)
  360.         {
  361.         (*function)(parameter);
  362.         return;
  363.         }
  364.         /* build new tag */
  365.     t->next = 0;
  366.     t->f = function;
  367.     t->p = parameter;
  368.     t->when = written;
  369.  
  370.         /* add it to list */
  371.     if (start) 
  372.         end->next = t;
  373.     else
  374.         start = t;
  375.     end = t;
  376.  
  377.         /* set up for next tag */
  378.     write(audio, buffer, 0);
  379.     written++;
  380.  
  381.     if (!tsync)
  382.         flush_tags();
  383.     }
  384.  
  385. void flush_buffer()
  386.    {
  387.     int actual;
  388.     int number;
  389.  
  390.     actual = write(audio, buffer, dsize * idx);
  391.     if (actual == -1)
  392.         notice("Write to audio failed");
  393.     else if (actual != dsize * idx)
  394.         notice("Short write to audio");
  395.     if (wait_samples)        
  396.         {        /* currently paused ? */
  397.         wait_samples -= actual;
  398.         if (wait_samples <= 0)
  399.             {    /* right number of samples gone by ? */
  400.             wait_samples = 0;
  401.             ainfo2.play.pause = FALSE;
  402.             ioctl(audio, AUDIO_SETINFO, &ainfo2);
  403.             }
  404.         }
  405.     if (tsync)
  406.         flush_tags();
  407.     idx = 0;
  408.    }
  409.  
  410. void discard_buffer()
  411.     {
  412.     remove_pending_tags();
  413.     ioctl(audio, I_FLUSH, FLUSHW);
  414.     if (wait_samples)
  415.         {
  416.         ainfo2.play.pause = FALSE;
  417.         ioctl(audio, AUDIO_SETINFO, &ainfo2);
  418.         wait_samples = 0;
  419.         }
  420.     set_synchronize();
  421.     }
  422.  
  423. void close_audio()
  424.    {
  425.     remove_pending_tags();
  426.     free(buffer);
  427.    close(audio);
  428.    }
  429.  
  430. int output_resolution()
  431.     {
  432.     return 16;
  433.     }
  434.